<template>
  <ContentWrap :bodyStyle="{ paddingTop: '5px' }">
    <back :backOption="backOption" />
    <div class="h-full">
      <el-form
        class="top-search"
        label-width="140px"
        :model="formData"
        ref="ElForm"
        :rules="rules"
        @submit.prevent
      >
        <el-row>
          <el-col :span="24" class="row-item">
            <el-form-item label="任务名称:" prop="name" class="col-item">
              <ns-input
                v-model="formData.name"
                placeholder="请输入任务名称"
                clearable
                :maxlength="50"
              />
            </el-form-item>
            <el-form-item class="col-item" label="探测目标IP/IP段:" prop="targetIps">
              <ns-input
                :rows="6"
                type="textarea"
                maxlength="500"
                v-model="formData.targetIps"
                @input="formData.targetIps = formData.targetIps.replace(/ /g, '')"
                placeholder=" 支持单个IP或IP段，多个IP或IP段以换行分开。例如：&#10; 192.168.1.1 &#10; 192.168.1.1/24 &#10; 192.168.1.1-128"
              />
            </el-form-item>
            <el-form-item class="col-item" label="探测例外:" prop="excludeIps">
              <ns-input
                :rows="6"
                type="textarea"
                maxlength="500"
                v-model="formData.excludeIps"
                @input="formData.excludeIps = formData.excludeIps.replace(/ /g, '')"
                placeholder=" 支持单个IP或IP段，多个IP或IP段以换行分开。例如：&#10; 192.168.1.1 &#10; 192.168.1.1/24 &#10; 192.168.1.1-128"
              />
            </el-form-item>
            <el-form-item label="描述" prop="field3" class="col-item">
              <ns-input
                :rows="6"
                type="textarea"
                maxlength="500"
                v-model="formData.field3"
                placeholder="请输入描述"
              />
            </el-form-item>
            <el-form-item label="数据源类型" prop="field1" class="col-item">
              <el-select
                v-model="formData.field1"
                clearable
                placeholder="请选择数据源类型"
                style="width: 220px"
              >
                <el-option label="结构化数据源" value="1" key="1" />
                <el-option label="非结构化数据源" value="2" key="2" />
              </el-select>
            </el-form-item>
            <el-form-item label="端口范围:" prop="field2" inline class="col-item">
              <ns-input
                style="width: 107px"
                v-model.number="formData.field2[0]"
                clearable
                :min="0"
                :max="65535"
                placeholder="请输入范围"
              />-
              <ns-input
                style="width: 107px"
                v-model.number="formData.field2[1]"
                clearable
                :min="0"
                :max="65535"
                placeholder="请输入范围"
              />
            </el-form-item>
            <el-form-item label="归属机构:" prop="deptId">
              <el-cascader
                ref="deptCascader"
                v-model="formData.deptId"
                placeholder="请选择归属机构"
                :props="cascaderProps"
                :options="deptList"
                filterable
                clearable
                value-on-clear=""
                :filter-method="sysFilterMethod"
              />
            </el-form-item>
            <el-form-item label="归属系统:" prop="sysId">
              <el-cascader
                ref="systemCascader"
                v-model="formData.sysId"
                placeholder="请选择归属系统"
                :props="systemCascaderProps"
                :options="systemList"
                filterable
                clearable
                value-on-clear=""
                :filter-method="sysFilterMethod"
              />
            </el-form-item>
            <el-form-item style="margin-bottom: 10px">
              <Icon icon="svg-icon:tips" />
              <span style="color: #cccccc">归属机构与归属系统至少填写一项</span>
            </el-form-item>
            <el-form-item label="扫描引擎" prop="deviceId">
              <el-select
                style="width: 20%"
                placeholder="请选择扫描引擎"
                v-model="formData.deviceId"
                clearable
              >
                <el-option
                  v-for="item in scanEngine"
                  :key="item.ip"
                  :label="item.name || item.id"
                  :value="item.ip"
                />
              </el-select>
            </el-form-item>
            <el-form-item label="扫描频率" prop="scanMethod">
              <el-radio-group v-model="formData.scanMethod">
                <el-radio :label="1">单次扫描</el-radio>
                <el-radio :label="2">定期扫描</el-radio>
              </el-radio-group>
            </el-form-item>
            <el-row v-if="formData.scanMethod == 2">
              <el-form-item label="执行周期" prop="detectionCycle">
                <el-select
                  style="width: 100px"
                  placeholder="频次"
                  v-model="formData.detectionCycle"
                  @change="handleDetectionCycleChange"
                  clearable
                >
                  <el-option label="每月" value="month" />
                  <el-option label="每周" value="week" />
                  <el-option label="每日" value="day" />
                </el-select>
              </el-form-item>
              <el-form-item
                v-if="formData.detectionCycle != 'day'"
                prop="detectionCycleNum"
                label-width="0px"
                ><el-select
                  clearable
                  placeholder="日期"
                  style="width: 100px"
                  class="mr15px"
                  v-model="formData.detectionCycleNum"
                >
                  <el-option
                    v-for="item in formData.detectionCycle == 'month'
                      ? dateList.month
                      : dateList.week"
                    :key="item.value"
                    :label="item.label"
                    :value="item.value"
                  /> </el-select
              ></el-form-item>
              <el-form-item prop="execTime" label-width="0px">
                <el-time-picker
                  clearable
                  v-model="formData.execTime"
                  arrow-control
                  value-format="YYYY-MM-DD HH:mm:ss"
                  placeholder="请选择时间"
                />
              </el-form-item>
            </el-row>
            <template v-if="formData.scanMethod == 2">
              <el-form-item label="开始时间" prop="taskStartTime">
                <el-date-picker
                  v-model="formData.taskStartTime"
                  type="date"
                  placeholder="请选择开始时间"
                  format="YYYY-MM-DD"
                  value-format="YYYY-MM-DD HH:mm:ss"
                />
              </el-form-item>
              <el-form-item label="结束时间" prop="taskEndTime">
                <el-date-picker
                  v-model="formData.taskEndTime"
                  type="date"
                  placeholder="请选择结束时间"
                  format="YYYY-MM-DD"
                  value-format="YYYY-MM-DD HH:mm:ss"
                />
              </el-form-item>
            </template>
            <el-form-item label="执行方式" v-if="formData.scanMethod == 1" prop="execMethod">
              <el-radio-group v-model="formData.execMethod">
                <el-radio :label="1">立即执行</el-radio>
                <el-radio :label="2">手动执行</el-radio>
                <el-radio :label="3">指定时间</el-radio>
              </el-radio-group>
            </el-form-item>
            <el-form-item
              label="选择时间"
              v-if="formData.execMethod == 3 && formData.scanMethod == 1"
              prop="execTime"
            >
              <el-date-picker
                clearable
                v-model="formData.execTime"
                type="datetime"
                value-format="YYYY-MM-DD HH:mm:ss"
                placeholder="请选择日期"
                :disabled-hours="disabledHours"
                :disabled-minutes="disabledMinutes"
                :disabled-seconds="disabledSeconds"
                :default-time="new Date()"
                :disabled-date="disabledDate"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <div style="text-align: center">
          <el-button @click="handleClose">取消</el-button>
          <el-button type="primary" @click="submit" :disabled="disabled">确定</el-button>
        </div>
      </el-form>
    </div>
  </ContentWrap>
</template>
<script setup>
import back from '@/components/Back/index.vue'
import { saveTask, editTask, getTaskDetail } from '@/api/asset/taskManage/dataSource'
import { useRouter } from 'vue-router'
import { sysFilterMethod } from '@/utils/selectFilter'
import { dateList } from '@/utils/dict'
import { devicePage } from '@/api/device'
import { handleTree } from '@/utils/tree'
import { getSimpleDeptList } from '@/api/system/dept'
import { getSimpleSystemList } from '@/api/asset/taskManage'
import dayjs from 'dayjs'
const route = useRoute()
const router = useRouter()
const disabled = ref(false)
const editId = ref(route.query.id)
const { proxy } = getCurrentInstance()
const deptList = ref([])
const systemList = ref([])
const message = useMessage() // 消息弹窗
const systemCascaderProps = reactive({
  checkStrictly: true,
  label: 'value',
  value: 'id',
  children: 'children',
  emitPath: false
})
const cascaderProps = reactive({
  checkStrictly: true,
  label: 'name',
  value: 'id',
  children: 'children',
  emitPath: false // 用于 cascader 组件：在选中节点改变时，是否返回由该节点所在的各级菜单的值所组成的数组，若设置 false，则只返回该节点的值
})
const backOption = reactive({
  title: '数据源探测任务'
})
const scanEngine = ref([])

const validateIp = (rule, value, callback) => {
  if (!value) {
    return callback(new Error('探测目标IP/IP段不能为空'))
  }
  const ipList = value.split('\n')
  const IPV4 =
    /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)(\/(?:3[0-2]|[12]?[0-9]))?(-(?:25[0-5]|2[0-4]\d|[1]?\d\d?))?$/
  for (let ip of ipList) {
    if (!IPV4.test(ip)) {
      return callback(new Error('IP地址格式不正确'))
    } else if (ip.includes('-')) {
      const [start, end] = ip.split('-')
      const [one, two, three, four] = start.split('.')
      if (Number(four) >= Number(end)) {
        return callback(new Error('IP地址格式不正确'))
      }
    }
  }
  callback()
}
const validateExcludeIp = (rule, value, callback) => {
  if (value !== '') {
    const ipList = value.split('\n')
    const IPV4 =
      /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)(\/(?:3[0-2]|[12]?[0-9]))?(-(?:25[0-5]|2[0-4]\d|[1]?\d\d?))?$/
    for (let ip of ipList) {
      if (!IPV4.test(ip)) {
        return callback(new Error('IP地址格式不正确'))
      } else if (ip.includes('-')) {
        const [start, end] = ip.split('-')
        const [one, two, three, four] = start.split('.')
        if (Number(four) >= Number(end)) {
          return callback(new Error('IP地址格式不正确'))
        }
      }
    }
  }
  callback()
}
const validatefield2 = (rule, value, callback) => {
  console.log(!value[0] && value[0] !== 0 && !value[1] && value[1] !== 0)

  if ((!!value[0] || value[0] === 0) && !!value[1]) {
    ;(value[1] > 65535 || value[0] < 0) && callback(new Error('端口范围不正确'))
    value[0] >= value[1] ? callback(new Error('端口范围不正确')) : callback()
  } else if (!value[0] && value[0] !== 0 && !value[1] && value[1] !== 0) {
    callback()
  } else {
    callback(new Error('端口范围不正确'))
  }
}

async function getDeptList() {
  const data = await getSimpleDeptList()
  deptList.value = data
  console.log(formData.value.deptId, 3213213123)
  if (formData.value.deptId == 0 && !editId.value) {
    formData.value.deptId = deptList.value[0].id || ''
  }
}
async function getSystemList() {
  const data = await getSimpleSystemList()
  systemList.value = handleTree(data, 'id', 'pid')
  if (!formData.value.sysId && !editId.value) {
    formData.value.sysId = systemList.value[0].id || ''
  }
}
const validateTime = (rule, value, callback) => {
  if (formData.value.taskStartTime && formData.value.taskEndTime) {
    const start = Date.parse(new Date(formData.value.taskStartTime).toString())
    const end = Date.parse(new Date(formData.value.taskEndTime).toString())
    if (rule.field == 'taskStartTime' || rule.fullField == 'taskStartTime') {
      if (start > end) {
        callback(new Error('开始时间不能大于结束时间'))
      } else {
        callback()
      }
    } else if (rule.field == 'taskEndTime' || rule.fullField == 'taskEndTime') {
      if (start > end) {
        callback(new Error('结束时间不能小于开始时间'))
      } else {
        callback()
      }
    }
  } else {
    callback()
  }
}
const data = reactive({
  formData: {
    name: '',
    type: 1,
    targetIps: '',
    excludeIps: '',
    scanMethod: 1,
    execMethod: 1,
    execTime: '',
    deviceId: '',
    taskStartTime: '',
    taskEndTime: '',
    deptId: '',
    sysId: '',
    field1: '',
    field2: [],
    field3: ''
  }
})
const isRequired = computed(() => {
  return !formData.value.deptId && !formData.value.sysId
})
const rules = computed(() => ({
  name: [{ required: true, message: '任务名称不能为空', trigger: 'blur' }],
  targetIps: [{ required: true, validator: validateIp, trigger: 'blur' }],
  excludeIps: [{ validator: validateExcludeIp, trigger: 'blur', required: false }],
  scanMethod: [{ required: true, message: '请选择扫描频率', trigger: 'change' }],
  execMethod: [{ required: true, message: '请选择执行方式', trigger: 'change' }],
  detectionCycle: [{ required: true, message: '请选择频次', trigger: 'change' }],
  execTime: [{ required: true, message: '请选择时间', trigger: 'change' }],
  deviceId: [{ required: true, message: '请选择扫描引擎', trigger: 'change' }],
  taskStartTime: [{ required: false, validator: validateTime, trigger: 'change' }],
  taskEndTime: [{ required: false, validator: validateTime, trigger: 'change' }],
  deptId: [{ required: isRequired.value, message: '归属机构不能为空', trigger: 'change' }],
  sysId: [{ required: isRequired.value, message: '归属系统不能为空', trigger: 'change' }],
  field2: [{ validator: validatefield2, trigger: 'blur', required: false }]
}))

let { formData } = toRefs(data)
onMounted(async () => {
  if (editId.value) {
    const data = await getTaskDetail({ id: editId.value })
    formData.value = data
    formData.value.field2 = formData.value.field2 ? formData.value.field2.split('-') : []
  }
  getSystemList()
  getDeptList()
  const { data } = await devicePage({ page: 1, pageSize: 100000, type: 2 })
  scanEngine.value = data
})
const handleDetectionCycleChange = (val) => {
  formData.value.detectionCycleNum = 1
}
const handleClose = () => {
  router.push({ name: 'TaskManage' })
}
const disabledDate = (time) => {
  return time.getTime() < Date.now() - 8.64e7
} /**
 * @description:限制选择此刻之前的时，下面分别是分和秒
 * @return {*}
 */
const disabledHours = () => {
  const a = []
  for (let i = 0; i < 24; i++) {
    // 限制之前 < 之后 >
    if (new Date().getHours() <= i) continue
    a.push(i)
  }
  return a
}
const disabledMinutes = () => {
  const a = []
  for (let i = 0; i < 60; i++) {
    // 限制之前 < 之后 >
    if (new Date().getMinutes() <= i) continue
    a.push(i)
  }
  return a
}
const disabledSeconds = () => {
  const a = []
  for (let i = 0; i < 60; i++) {
    // 限制之前 < 之后 >
    if (new Date().getSeconds() <= i) continue
    a.push(i)
  }
  return a
}
const submit = () => {
  proxy.$refs.ElForm.validate(async (valid) => {
    if (valid) {
      disabled.value = true
      if (!formData.value.sysId) {
        formData.value.system = ''
      }
      if (formData.value.field2.length == 2) {
        formData.value.field2 = formData.value.field2[0] + '-' + formData.value.field2[1]
      } else {
        formData.value.field2 = ''
      }
      if (editId.value) {
        const { code } = await editTask(
          Object.assign({}, formData.value, {
            id: editId.value,
            type: 1,
            taskType: 1,
            deptId: formData.value.deptId == '' ? '0' : formData.value.deptId
          })
        ).catch(() => {
          disabled.value = false
        })
        code == 200 ? message.success('修改成功') : message.error('修改失败')
        code == 200 && handleClose()
      } else {
        const { code } = await saveTask({
          ...formData.value,
          type: 1,
          taskType: 1,
          deptId: formData.value.deptId == '' ? '0' : formData.value.deptId
        }).catch(() => {
          disabled.value = false
        })
        code == 200 ? message.success('新增成功') : message.error('新增失败')
        code == 200 && handleClose()
      }
      disabled.value = false
    }
  })
}
</script>

<style scoped lang="scss">
.top-search {
  .el-form-item__label {
    justify-content: start;
  }
  .dialog-footer {
    padding: 80px;
    display: flex;
    justify-content: center;
  }
}

.row-item {
  padding: 20px 100px;

  .col-item {
    width: 80%;
    padding-right: 30px;
    margin-right: 0;
  }
}

.m-section-title {
  margin-bottom: 8px;
  height: 24px;
  line-height: 24px;
  font-size: 16px;

  &::before {
    content: ' ';
    display: inline-block;
    width: 4px !important;
    height: 16px;
    background-color: var(--el-color-primary);
    margin-right: 10px;
    position: relative;
    top: 3px;
  }

  .m-section-title__text {
    font-weight: 500;
    font-family: PingFangSC-Medium;
  }
}
</style>
